﻿using System;

namespace Ue.Infrastructure.Caching.VolatileProvider
{
    /// <summary>
    /// 时间缓存机制，超过指定的时间则缓存过期
    /// </summary>
    public interface IClock
    {
        DateTime UtcNow { get; }

        /// <summary>
        /// 指定一个时间间隔，以UtcNow时间开始，（UtcNow+间隔时间）为结束缓存时间
        /// 例如：用来实现，超过10分钟更新缓存
        /// </summary>
        /// <param name="duration"></param>
        /// <returns></returns>
        IVolatileToken When(TimeSpan duration);

        /// <summary>
        /// 指定是个固定时间值，超过这个时间值则缓存过期
        /// </summary>
        /// <param name="absoluteUtc"></param>
        /// <returns></returns>
        IVolatileToken WhenUtc(DateTime absoluteUtc);
    }

    public class Clock : IClock
    {
        public DateTime UtcNow
        {
            get { return DateTime.UtcNow; }
        }

        public IVolatileToken When(TimeSpan duration)
        {
            return new AbsoluteExpirationToken(this, duration);
        }

        public IVolatileToken WhenUtc(DateTime absoluteUtc)
        {
            return new AbsoluteExpirationToken(this, absoluteUtc);
        }

        public class AbsoluteExpirationToken : IVolatileToken
        {
            private readonly IClock _clock;
            private readonly DateTime _invalidateUtc;

            public AbsoluteExpirationToken(IClock clock, DateTime invalidateUtc)
            {
                _clock = clock;
                _invalidateUtc = invalidateUtc;
            }

            public AbsoluteExpirationToken(IClock clock, TimeSpan duration)
            {
                _clock = clock;
                _invalidateUtc = _clock.UtcNow.Add(duration);
            }

            public bool IsCurrent
            {
                get { return _clock.UtcNow < _invalidateUtc; }
            }
        }
    }
}
